package editor.graphics;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;

import javax.swing.JOptionPane;
import javax.swing.event.MouseInputListener;

import editor.dxf.DxfModel;
import editor.graphics.EditorMapa.Estado;
import editor.modelo.LandMark;
import editor.modelo.Portal;
import editor.modelo.EditorSpace;

public class EditorEventHandler implements MouseInputListener, MouseWheelListener {

	private Object dragging;
	private EditorMapa editor;
	// Ultima ubicacion del mouse conocida
	float xMouse;
	float yMouse;
	private float anchorX;
	private float anchorY;
	private float initialOrX;
	private float initialOrY;

	public EditorEventHandler(EditorMapa editor) {
		this.editor = editor;
		editor.addMouseListener(this);
		editor.addMouseMotionListener(this);
		editor.addMouseWheelListener(this);
	}
	
	

	@Override
	public void mouseMoved(MouseEvent e) {
		switch (editor.getEstado()) {
		case agregarEspacio: {
			cargarCoordenadasMouse(e.getX(), e.getY());
			editor.repaint();
			break;
		}
		case agregarPuntos: {
			cargarCoordenadasMouse(e.getX(), e.getY());
			editor.repaint();
			break;
		}
		case agregarLandMark: {
			cargarCoordenadasMouse(e.getX(), e.getY());
			editor.repaint();
			break;
		}
		}
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		// if(e.getButton()!= MouseEvent.BUTTON1) return;
		switch (editor.getEstado()) {
		case correrCamara: {

			cargarCoordenadasMouse(e.getX(), e.getY());
			editor.origenX = initialOrX - (anchorX - e.getX())
					/ editor.getZoom();
			editor.origenY = initialOrY - (anchorY - e.getY())
					/ editor.getZoom();
			//System.out.println(e.getX() + "--" + e.getY());
			//System.out.println(editor.origenX + " " + editor.origenY);
			editor.repaint();
			break;
		}
		case drag: {
			cargarCoordenadasMouse(e.getX(), e.getY());
			if (dragging instanceof EditorSpace) {
				if (editor.seleccion.isSpaceSelected()) {
					editor.seleccion.getLastSelectedSpace().setCentro(xMouse,
							yMouse);
					editor.repaint();
				}
			} else if (dragging instanceof Point2D) {
				if (editor.seleccion.isPointSelected()) {
					editor.seleccion.getLastSelectedPoint().setLocation(xMouse,
							yMouse);
					editor.repaint();
				}
			} else if (dragging instanceof LandMark) {
				((LandMark) dragging).setCentro(xMouse, yMouse);
				editor.repaint();
			}
			break;

		}
		case inactivo: {
			if (dragging != null) {
				editor.setEstado(Estado.drag);
				editor.save();
			}
			break;
		}
		}
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if (!editor.hasFocus())
			editor.requestFocus();
		if (e.getButton() == MouseEvent.BUTTON3) {
			cargarCoordenadasMouse(e.getX(), e.getY());
			editor.botonDerecho(xMouse, yMouse);
			return;
		}
		if (e.getButton() != MouseEvent.BUTTON1)
			return;
		cargarCoordenadasMouse(e.getX(), e.getY());
		if (e.isControlDown()) { // agrego a la seleccion
			EditorSpace s = editor.seleccion.seleccionarSpace(
					editor.getSelectedFloor(),
					new Point2D.Float(xMouse, yMouse));
			if (s != null) {
				editor.seleccion.addSpace(s);
			} else {
				Point2D pto = editor.seleccion
						.seleccionarPunto(new Point2D.Float(xMouse, yMouse));
				if (pto != null){
					editor.seleccion.addPoint(pto);
				
				}
			}
			editor.repaint();
			return;
		}//
		if( e.isAltDown()){
			((DxfModel)editor.fondo).generarSpace((int)xMouse, (int)yMouse, editor.getPisoEnEdicion());
	//		((DxfModel)editor.fondo).generateFloor(editor.getPisoEnEdicion());
		
			return;
		}
		if (e.isShiftDown()) { // corro la camara
			anchorX = e.getX();
			anchorY = e.getY();
			initialOrX = editor.origenX;
			initialOrY = editor.origenY;
			editor.setEstado(Estado.correrCamara);
			editor.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
			return;
		}
		if (editor.getEstado() != Estado.inactivo)
			return;
		else { // selecciono 1 sola cosa
			Point2D.Float ptoM = new Point2D.Float(xMouse, yMouse);
			// seleccion.vaciarPuntos();
			EditorSpace sp = editor.seleccion.seleccionarSpace(
					editor.getSelectedFloor(), ptoM);
			if (sp != null) {
				editor.seleccion.selectSpace(sp);
				// setEstado(Estado.drag);
				dragging = sp;
			} else {
				Point2D pto = editor.seleccion.seleccionarPunto(ptoM);
				if (pto != null) {
					editor.seleccion.selectPoint(pto);
					// setEstado(Estado.drag);
					dragging = pto;
					
				} else {
					LandMark lm = editor.seleccion.seleccionarLandmark(
							editor.getSelectedFloor(), ptoM);
					if (lm != null) {
						editor.seleccion.selectLandMark(lm);
						dragging = lm;
					} else {
						Portal p = editor.seleccion.seleccionarPortal(editor
								.getSelectedFloor(), new Point2D.Float(xMouse,
								yMouse));
						// if(p!= null){
						editor.seleccion.selectPortal(p);
						// System.out.println("portal seleccionado");
						// } else seleccion.vaciarPortals();
					}
				}

			}

			editor.repaint();
		}

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		if (e.getButton() != MouseEvent.BUTTON1)
			return;
		if (editor.getEstado() == Estado.correrCamara) {
			editor.setEstado(Estado.inactivo);
			editor.setCursor(Cursor.getDefaultCursor());
		}
		if (editor.getEstado() == Estado.drag) {
			editor.setEstado(Estado.inactivo);
			dragging = null;
		}
		//
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		if (e.getButton() != MouseEvent.BUTTON1)
			return;
		if (e.isControlDown())
			return;
		if (e.isShiftDown())
			return;

		cargarCoordenadasMouse(e.getX(), e.getY());

		switch (editor.getEstado()) {
		case agregarEspacio: {
			editor.setEstado(Estado.inactivo);
			editor.seleccion.selectSpace(editor.getSelectedFloor().addNewSpace(
					xMouse, yMouse));
			editor.repaint();
			break;
		}
		case agregarLandMark: {
			if (!editor.seleccion.isSpaceSelected()) {
				JOptionPane.showMessageDialog(editor,
						"Debe seleccionar un espacio para agregar Marcas");
				return;
			}
			editor.setEstado(Estado.inactivo);
			editor.seleccion.selectLandMark(editor.getSelectedFloor()
					.addNewLandMark(
							xMouse,
							yMouse,
							((EditorSpace) editor.seleccion
									.getLastSelectedSpace())));
			editor.repaint();
			break;
		}
		case agregarPuntos: {
			if (!editor.seleccion.isSpaceSelected()) {
				JOptionPane.showMessageDialog(editor,
						"Debe seleccionar un espacio para agregar puntos");
				return;
			}
			Point2D.Float pto = new Point.Float(xMouse, yMouse);
			((EditorSpace) editor.seleccion.getLastSelectedSpace())
					.insertPointAfter(pto,
							editor.seleccion.getLastSelectedPoint());
			editor.seleccion.selectPoint(pto);
			editor.repaint();
			break;
		}
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	void cargarCoordenadasMouse(int x, int y) {
		xMouse = editor.aCoordenadasMundoX(x);
		yMouse = editor.aCoordenadasMundoY(y);
	}



	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
	//	System.out.println("cambiando zoom");
	//	System.out.println(editor.getZoom());
	//	System.out.println(e.getWheelRotation());
		editor.adjustZoom(((int) (-e.getWheelRotation()*10)));
		editor.repaint();
		
	}

}
